<template>
  <div
    ref="searchForm"
    class="searchFormDiv"
    v-click-outside="onBlur"
    :class="{ 'input-focus': data.inputFocus, 'show-histories': showHistories }"
  >
    <form action="/search" method="GET" class="search-input">
      <input
        v-model="data.keyword"
        name="q"
        class="input"
        type="text"
        maxlength="30"
        placeholder="输入你想查找的内容"
        autocomplete="off"
        aria-autocomplete="off"
        @focus="onFocus"
        @input="onInput"
        @keyup.down="changeSelect(1)"
        @keyup.up="changeSelect(-1)"
        @keyup.enter="searchBoxOnEnter"
      />
      <span @click="submitSearch">
        <i class="iconfont icon-search" />
      </span>
    </form>
    <div class="histories">
      <ul>
        <li
          v-for="(item, index) in histories"
          :key="index"
          :class="{ selected: index === data.selectedIndex }"
          @mouseover="historyItemMouseOver(index)"
          @mouseout="historyItemMouseOut()"
        >
          <span @click="historyItemClick(item)">{{ item }}</span>
          <i class="iconfont icon-close" @click="deleteHistory(item)" />
        </li>
      </ul>
    </div>
  </div>
</template>

<script setup>
const localStorageKey = "bbsgo.search.histories";
const maxHistoryLen = 10;
const route = useRoute();

const data = reactive({
  keyword: route.query.q || "",
  inputFocus: false,
  selectedIndex: -1,
  allHistories: [],
});

const showHistories = computed(() => {
  return (
    data.inputFocus && histories && histories.value && histories.value.length
  );
});

const histories = computed(() => {
  if (data.keyword) {
    return data.allHistories.filter((history) => {
      return history.includes(data.keyword);
    });
  }
  return data.allHistories;
});

onMounted(() => {
  loadAllHistories();
});

const searchBoxOnEnter = (e) => {
  e.stopPropagation();

  // 如果选中了历史搜索记录，那么使用历史搜索记录
  if (
    data.selectedIndex >= 0 &&
    histories.value &&
    histories.value.length > data.selectedIndex
  ) {
    data.keyword = histories.value[data.selectedIndex];
  }
  submitSearch();
};
const historyItemClick = (keyword) => {
  data.keyword = keyword;
  submitSearch();
};
const submitSearch = () => {
  if (!data.keyword) {
    return;
  }
  addHistories();
  window.location = "/search?q=" + encodeURIComponent(data.keyword);
};
const onFocus = () => {
  data.inputFocus = true;
};
const onBlur = () => {
  data.inputFocus = false;
};
const onInput = () => {
  data.selectedIndex = -1;
};
const changeSelect = (delta) => {
  if (!histories.value || !histories.value.length) {
    return;
  }
  let index = data.selectedIndex + delta;
  if (index < 0) {
    // 选中熬第一个了，再往上取消选中
    index = -1;
  } else if (index >= histories.value.length) {
    // 选中到最后了，再往下就回到第一个
    index = 0;
  }
  data.selectedIndex = index;
};
const historyItemMouseOver = (index) => {
  data.selectedIndex = index;
};
const historyItemMouseOut = () => {
  data.selectedIndex = -1;
};
const loadAllHistories = () => {
  try {
    data.allHistories = JSON.parse(localStorage.getItem(localStorageKey)) || [];
  } catch (error) {
    data.allHistories = [];
  }
};
const addHistories = () => {
  if (!data.keyword) {
    return;
  }
  const newArray = [];
  newArray.push(data.keyword);
  if (data.allHistories && data.allHistories.length) {
    for (let i = 0; i < data.allHistories.length; i++) {
      const element = data.allHistories[i];
      if (newArray.length < maxHistoryLen && !newArray.includes(element)) {
        newArray.push(element);
      }
    }
  }
  localStorage.setItem(localStorageKey, JSON.stringify(newArray));
  data.allHistories = newArray;
};
const deleteHistory = (kw) => {
  const newArray = [];
  if (data.allHistories && data.allHistories.length) {
    for (let i = 0; i < data.allHistories.length; i++) {
      const element = data.allHistories[i];
      if (element !== kw && !newArray.includes(element)) {
        newArray.push(element);
      }
    }
  }
  localStorage.setItem(localStorageKey, JSON.stringify(newArray));
  data.allHistories = newArray;
};
</script>

<style lang="scss" scoped>
.searchFormDiv {
  @media screen and (max-width: 768px) {
    & {
      display: none;
    }
  }

  $search-box-width: 280px;
  $search-box-unfocus-width: 180px;
  $focus-color: #0065ff; // TODO

  &.input-focus {
    .search-input {
      background-color: var(--bg-color);
      border: 1px solid var(--border-color3);
    }
    .icon-search {
      color: $focus-color;
    }
  }

  &.show-histories {
    .histories {
      display: block;
    }
  }

  .search-input {
    width: $search-box-unfocus-width;
    background-color: var(--bg-color2);
    border: 1px solid var(--border-color);
    height: 34px;
    border-radius: 17px;
    padding: 4px 10px;
    font-size: 14px;
    display: flex;
    transition-property: background-color, border, color;
    transition-duration: 0.25s;
    transition-timing-function: ease-in;
    transition: width 0.5s;

    &:has(.input:focus) {
      width: $search-box-width;
      border: 1px solid $focus-color;
    }

    input {
      color: var(--text-color);
      font-weight: 400;
      font-size: 13px;
      height: 100%;
      width: 100%;
      flex: 1 1;
      padding: 0;
      margin: 0 5px;
      overflow: hidden;
      background: transparent;
      border: none;
      resize: none;
      box-shadow: none;

      &:focus {
        outline: none;
      }
    }
  }

  span {
    padding: 0 4px 0 10px;
    cursor: pointer;
  }

  .histories {
    width: $search-box-width;
    display: none;
    height: auto;
    top: 48px;
    position: fixed;

    background-color: var(--bg-color);
    border: 1px solid var(--border-color);
    border-radius: 4px;
    box-shadow: 0 5px 20px rgb(18 18 18 / 10%);
    z-index: 203;

    animation: showHistoriesAnimation 0.3s;
    -moz-animation: showHistoriesAnimation 0.3s; /* Firefox */
    -webkit-animation: showHistoriesAnimation 0.3s; /* Safari and Chrome */
    -o-animation: showHistoriesAnimation 0.3s; /* Opera */

    @keyframes showHistoriesAnimation {
      0% {
        opacity: 0;
        transform: translate(1px, 30px);
      }
      100% {
        opacity: 1;
        transform: translate(0, 0);
      }
    }
    ul {
      li {
        padding: 7px 16px;
        width: 100%;
        text-align: left;
        cursor: pointer;
        -webkit-box-sizing: border-box;
        box-sizing: border-box;

        display: flex;
        span {
          width: 100%;
          font-size: 13px;
          font-weight: 400;
          color: var(--text-color);
        }
        &:hover {
          i.iconfont {
            display: block;
          }
        }
        i.iconfont {
          display: none;
          font-size: 13px;
          padding: 0 6px;
          &:hover {
            color: #4e6ef2;
          }
        }
        &.selected {
          background-color: var(--bg-color2);
        }
      }
    }
  }
}
</style>
